package com.example.demo.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.dto.OrderQueryDTO;
import com.example.demo.mapper.OrdersMapper;
import com.example.demo.pojo.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.service.*;
import com.example.demo.vo.OrderListVO;
import com.example.demo.vo.OrdersDevVO;
import com.example.demo.vo.ResultVO;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;

import static org.apache.catalina.manager.StatusTransformer.formatTime;

@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private CustomerService customerService;
    @Autowired
    private BoardroomStateService boardroomStateService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private BoardroomService boardroomService;

    @Override
    @Transactional
    public ResultVO addOrder(Integer boardroomId, Integer customerId, String bookingDate, String startTime, String endTime, Integer numPeople, Integer state, Double totalPrice) throws Exception {
        // 校验参数
        if (boardroomId == null || customerId == null || bookingDate == null ||
                startTime == null || endTime == null || numPeople == null ||
                state == null || totalPrice == null) {
            throw new IllegalArgumentException("订单参数不完整");
        }

        // 将字符串日期和时间转换为 Date 类型
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");

        try {
            Date bookingDateParsed = dateFormat.parse(bookingDate);
            Date startTimeParsed = timeFormat.parse(startTime);
            Date endTimeParsed = timeFormat.parse(endTime);

            // 创建 Orders 实体
            Orders order = new Orders();
            order.setAddDate(new Date());
            order.setBoardroomId(boardroomId);
            order.setCustomerId(customerId);
            order.setBookingDate(bookingDateParsed);
            order.setStartTime(startTimeParsed);
            order.setEndTime(endTimeParsed);
            order.setNumPeople(numPeople);
            order.setState(state);
            order.setTotalPrice(totalPrice);

            // 创建 BoardroomState 实体
            BoardroomState boardroomState = new BoardroomState();
            boardroomState.setBoardroomId(boardroomId);
            boardroomState.setDate(bookingDateParsed);
            boardroomState.setStartTime(startTimeParsed);
            boardroomState.setEndTime(endTimeParsed);

            // 根据订单状态设置会议室状态
            if (state == 2) { // 用户选择立即支付
                Customer customer = customerService.getById(customerId);
                if (customer == null || customer.getBalance() < totalPrice) {
                    return ResultVO.fail("余额不足，请先充值");
                }

                // 扣除余额
                customer.setBalance(customer.getBalance() - totalPrice);
                customerService.updateById(customer);

                // 设置会议室状态为3（预订）
                boardroomState.setState(3);
            } else { // 用户选择稍后支付
                // 设置会议室状态为2（锁定）
                boardroomState.setState(2);
            }

            // 插入会议室状态表
            boardroomStateService.save(boardroomState);

            // 插入订单表
            Integer boardroomStateId = boardroomState.getId();
            order.setStateId(boardroomStateId);
            this.save(order);

            // 根据支付状态返回不同的结果
            return state == 2 ? ResultVO.success("支付成功") : ResultVO.success("预定成功");
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期或时间格式不正确，请确保日期格式为 yyyy-MM-dd，时间格式为 HH:mm", e);
        }
    }

    // 添加定时任务，每分钟检查一次
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    @Transactional
    public void checkUnpaidOrders() {
        // 获取当前时间
        Date now = new Date();
        // 计算30分钟前的时间
        Date thirtyMinutesAgo = new Date(now.getTime() - 30 * 60 * 1000);

        // 查询状态为1(未支付)且创建时间超过30分钟的订单
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("state", 1)
                .lt("add_date", thirtyMinutesAgo);

        List<Orders> unpaidOrders = this.list(queryWrapper);

        // 批量更新这些订单状态为4(已取消)
        if (!unpaidOrders.isEmpty()) {
            unpaidOrders.forEach(order -> {
                // 1. 更新订单状态为4(已取消)
                order.setState(4); // 4代表已取消
                order.setCancelDate(now); // 设置取消时间

                // 2. 删除对应的boardroomState记录，没有即表示空闲
                if (order.getStateId() != null) {
                    boardroomStateService.removeById(order.getStateId());
                }
            });

            // 批量更新订单状态
            this.updateBatchById(unpaidOrders);
        }
    }

    @Override
    @Transactional
    public ResultVO modifyOrder(Integer orderId, Integer customerId) {
        // 校验参数
        if (orderId == null || customerId == null) {
            throw new IllegalArgumentException("订单ID或客户ID不能为空");
        }

        // 查询订单信息
        Orders order = this.getById(orderId);
        if (order == null) {
            return ResultVO.fail("订单不存在");
        }

        // 检查订单是否属于该客户
        if (!order.getCustomerId().equals(customerId)) {
            return ResultVO.fail("您无权修改此订单");
        }

        Date now = new Date();
        Date thirtyMinutesAgo = new Date(now.getTime() - 30 * 60 * 1000);
        if (order.getAddDate().before(thirtyMinutesAgo)) {
            return ResultVO.fail("订单已超时，请重新预订");
        }

        // 查询客户信息
        Customer customer = customerService.getById(customerId);
        if (customer == null) {
            return ResultVO.fail("客户信息不存在");
        }

        // 检查客户余额是否足够支付订单
        if (customer.getBalance() < order.getTotalPrice()) {
            return ResultVO.fail("余额不足，请先充值");
        }

        // 查询对应的会议室状态信息
        BoardroomState boardroomState = boardroomStateService.getById(order.getStateId());
        if (boardroomState == null) {
            return ResultVO.fail("会议室状态信息不存在");
        }

        // 扣除客户余额
        customer.setBalance(customer.getBalance() - order.getTotalPrice());
        customerService.updateById(customer);

        // 修改订单状态为2（已支付）
        order.setState(2);
        this.updateById(order);

        // 修改会议室状态为3（预订）
        boardroomState.setState(3);
        boardroomStateService.updateById(boardroomState);

        return ResultVO.success("订单状态修改成功，会议室状态已更新");
    }

    @Override
    public IPage<OrdersDevVO> queryOrdersByCustomerId(Integer customerId, Integer page, Integer pageSize) {
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_id", customerId).orderByDesc("id"); // 在数据库查询时就按ID降序
        IPage<Orders> ordersPage = this.page(new Page<>(page, pageSize), queryWrapper);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 定义日期格式
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); // 定义时间格式
        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 定义日期时间格式

        List<OrdersDevVO> ordersDevVOList = ordersPage.getRecords().stream().map(order -> {
            // 获取会议室信息
            Boardroom boardroom = boardroomService.getById(order.getBoardroomId());
            // 获取设备信息
            List<Device> devices = deviceService.findByBoardroomId(order.getBoardroomId());

            // 格式化 startTime 和 endTime 为 yyyy-MM-dd HH:mm:ss 格式
            try {
                // 获取日期部分
                String bookingDateStr = dateFormat.format(order.getBookingDate());

                // 获取时间部分
                String startTimeStr = timeFormat.format(order.getStartTime());
                String endTimeStr = timeFormat.format(order.getEndTime());

                // 合并日期和时间
                String startDateTimeStr = bookingDateStr + " " + startTimeStr;
                String endDateTimeStr = bookingDateStr + " " + endTimeStr;

                // 设置格式化后的时间字符串到 Orders 对象
                order.setStartTime(dateTimeFormat.parse(startDateTimeStr));
                order.setEndTime(dateTimeFormat.parse(endDateTimeStr));
            } catch (ParseException e) {
                throw new RuntimeException("时间格式化错误", e);
            }

            // 格式化 startTime 和 endTime 为 HH:mm 格式
            String startTimeHHmm = new SimpleDateFormat("HH:mm").format(order.getStartTime());
            String endTimeHHmm = new SimpleDateFormat("HH:mm").format(order.getEndTime());

            return new OrdersDevVO(order, boardroom, devices, startTimeHHmm, endTimeHHmm);
        }).collect(Collectors.toList());

        IPage<OrdersDevVO> resultPage = new Page<>(ordersPage.getCurrent(), ordersPage.getSize(), ordersDevVOList.size());
        resultPage.setRecords(ordersDevVOList);
        resultPage.setTotal(ordersPage.getTotal());

        return resultPage;
    }

    @Override
    @Transactional
    public ResultVO<Double> applyCancelOrder(Integer orderId) {
        // 校验参数
        if (orderId == null) {
            throw new IllegalArgumentException("订单ID不能为空");
        }

        // 查询订单信息
        Orders order = this.getById(orderId);
        if (order == null) {
            return ResultVO.fail("订单不存在");
        }

        // 检查订单状态是否允许退订
        if (order.getState() != 1 && order.getState() != 2) {
            return ResultVO.fail("当前订单状态不允许退订");
        }

        // 获取当前时间
        Instant now = Instant.now();

        // 组合预定时间（使用Java 8的日期时间API避免时区问题）
        LocalDate bookingDate = order.getBookingDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalTime startTime = order.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
        ZonedDateTime bookingDateTime = ZonedDateTime.of(bookingDate, startTime, ZoneId.systemDefault());

        // 计算时间差
        Duration duration = Duration.between(now, bookingDateTime.toInstant());
        long diffInMinutes = duration.toMinutes();

        // 对于已支付订单，检查是否在24小时内
        if (order.getState() == 2 && diffInMinutes < 24 * 60) {
            return ResultVO.fail("已支付订单24小时内不可退订");
        }

        // 根据时间差计算退款金额
        double refundAmount = 0.0;
        if (order.getState() == 2) {
            if (diffInMinutes > 72 * 60) {
                refundAmount = order.getTotalPrice();
            } else if (diffInMinutes > 48 * 60) {
                refundAmount = order.getTotalPrice() * 0.75;
            } else if (diffInMinutes >= 24 * 60) {
                refundAmount = order.getTotalPrice() * 0.25;
            }
        }

        // 更新订单状态为3（审核中）
        order.setState(3);
        order.setCancelDate(Date.from(now));
        order.setCancelPrice(refundAmount);
        this.updateById(order);

        return ResultVO.success("退订成功", refundAmount);
    }

    @Override
    public IPage<OrderListVO> queryOrdersByCondition(OrderQueryDTO queryDTO) {
        // 设置分页参数
        Page<Orders> page = new Page<>(queryDTO.getPage(), queryDTO.getPageSize());

        // 构建查询条件
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");

        // 1. 订单编号查询
        if (StringUtils.isNotBlank(queryDTO.getOrderId())) {
            try {
                int orderId = Integer.parseInt(queryDTO.getOrderId());
                queryWrapper.eq("id", orderId);
            } catch (NumberFormatException e) {
                // 不是有效的数字，不添加条件
            }
        }

        // 2. 订单状态查询
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq("state", queryDTO.getStatus());
        }

        // 3. 预定日期查询
        if (queryDTO.getReserveTime() != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            queryWrapper.eq("booking_date", sdf.format(queryDTO.getReserveTime()));
        }

        // 4. 预定人查询 - 先查询符合条件的客户ID
        Set<Integer> customerIds = new HashSet<>();
        if (StringUtils.isNotBlank(queryDTO.getBooker())) {
            QueryWrapper<Customer> customerWrapper = new QueryWrapper<>();
            customerWrapper.like("name", queryDTO.getBooker());
            List<Customer> customers = customerService.list(customerWrapper);
            customerIds = customers.stream()
                    .map(Customer::getId)
                    .collect(Collectors.toSet());

            // 如果没有找到匹配的客户，直接返回空结果
            if (customerIds.isEmpty()) {
                return new Page<>(page.getCurrent(), page.getSize(), 0);
            }
            queryWrapper.in("customer_id", customerIds);
        }

        // 5. 房间号查询 - 先查询符合条件的会议室ID
        Set<Integer> boardroomIds = new HashSet<>();
        if (StringUtils.isNotBlank(queryDTO.getRoomNumber())) {
            QueryWrapper<Boardroom> boardroomWrapper = new QueryWrapper<>();
            boardroomWrapper.like("name", queryDTO.getRoomNumber());
            List<Boardroom> boardrooms = boardroomService.list(boardroomWrapper);
            boardroomIds = boardrooms.stream()
                    .map(Boardroom::getId)
                    .collect(Collectors.toSet());

            // 如果没有找到匹配的会议室，直接返回空结果
            if (boardroomIds.isEmpty()) {
                return new Page<>(page.getCurrent(), page.getSize(), 0);
            }
            queryWrapper.in("boardroom_id", boardroomIds);
        }

        // 执行分页查询
        IPage<Orders> ordersPage = this.page(page, queryWrapper);

        // 获取所有订单ID
        List<Integer> orderIds = ordersPage.getRecords().stream()
                .map(Orders::getId)
                .collect(Collectors.toList());

        // 如果没有数据，直接返回空分页
        if (orderIds.isEmpty()) {
            return new Page<>(ordersPage.getCurrent(), ordersPage.getSize(), ordersPage.getTotal());
        }

        // 批量查询关联数据
        Map<Integer, Boardroom> boardroomMap = getBoardroomsByOrderIds(orderIds);
        Map<Integer, Customer> customerMap = getCustomersByOrderIds(orderIds);
        Map<Integer, List<Device>> deviceMap = getDevicesByOrderIds(orderIds);

        // 转换为VO
        IPage<OrderListVO> resultPage = new Page<>(
                ordersPage.getCurrent(),
                ordersPage.getSize(),
                ordersPage.getTotal()
        );

        resultPage.setRecords(ordersPage.getRecords().stream().map(order -> {
            OrderListVO vo = new OrderListVO();

            // 设置基础信息
            vo.setOrderId(order.getId());
            vo.setStartTime(formatTime(order.getStartTime()));
            vo.setEndTime(formatTime(order.getEndTime()));
            vo.setAttendees(order.getNumPeople());
            vo.setTotalAmount(order.getTotalPrice());
            vo.setStatus(order.getState());
            vo.setBoardroomId(order.getBoardroomId());
            vo.setCustomerId(order.getCustomerId());

            // 设置预定日期
            if (order.getBookingDate() != null) {
                vo.setBookingDate(new SimpleDateFormat("yyyy-MM-dd").format(order.getBookingDate()));
            }

            // 设置会议室信息
            Boardroom boardroom = boardroomMap.get(order.getBoardroomId());
            if (boardroom != null) {
                vo.setRoomName(boardroom.getName());
            }

            // 设置预定人信息
            Customer customer = customerMap.get(order.getCustomerId());
            if (customer != null) {
                vo.setBooker(customer.getName());
            }

            // 设置设备信息
            List<Device> devices = deviceMap.get(order.getBoardroomId());
            if (devices != null) {
                vo.setEquipment(devices.stream()
                        .map(Device::getName)
                        .collect(Collectors.toList()));
            }

            //设置退款金额
            Double cancelPrice = order.getCancelPrice();
            if(cancelPrice != null) {
                vo.setCancelPrice(cancelPrice);
            }

            //设置退款日期
            if(order.getCancelPrice() != null) {
                vo.setCancelDate(new SimpleDateFormat("yyyy-MM-dd").format(order.getCancelDate()));
            }
            return vo;
        }).collect(Collectors.toList()));

        return resultPage;
    }

    private String formatTime(Date time) {
        if (time == null) return "";
        return new SimpleDateFormat("HH:mm").format(time);
    }

    private Map<Integer, List<Device>> getDevicesByOrderIds(List<Integer> orderIds) {
        // 获取订单中的会议室ID
        Set<Integer> boardroomIds = orderIds.stream()
                .map(id -> {
                    Orders order = this.getById(id);
                    return order != null ? order.getBoardroomId() : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (boardroomIds.isEmpty()) return new HashMap<>();

        // 批量查询设备
        QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("boardroom_id", boardroomIds);
        List<Device> devices = deviceService.list(queryWrapper);

        return devices.stream()
                .collect(Collectors.groupingBy(Device::getBoardroomId));
    }

    private Map<Integer, Customer> getCustomersByOrderIds(List<Integer> orderIds) {
        // 获取订单中的客户ID
        Set<Integer> customerIds = orderIds.stream()
                .map(id -> {
                    Orders order = this.getById(id);
                    return order != null ? order.getCustomerId() : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (customerIds.isEmpty()) return new HashMap<>();

        // 批量查询客户
        return customerService.listByIds(customerIds).stream()
                .collect(Collectors.toMap(Customer::getId, customer -> customer));
    }

    private Map<Integer, Boardroom> getBoardroomsByOrderIds(List<Integer> orderIds) {
        // 获取订单中的会议室ID
        Set<Integer> boardroomIds = orderIds.stream()
                .map(id -> {
                    Orders order = this.getById(id);
                    return order != null ? order.getBoardroomId() : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (boardroomIds.isEmpty()) return new HashMap<>();

        // 批量查询会议室
        return boardroomService.listByIds(boardroomIds).stream()
                .collect(Collectors.toMap(Boardroom::getId, boardroom -> boardroom));
    }

    @Override
    @Transactional
    public ResultVO approveOrder(Integer orderId) {
        // 1. 获取订单信息
        Orders order = getById(orderId);
        if (order == null) {
            return ResultVO.fail("订单不存在");
        }

        // 2. 更新订单状态为已取消(4)
        order.setState(4);
        updateById(order);

        // 3. 删除关联的会议室状态记录
        if (order.getStateId() != null) {
            boardroomStateService.removeById(order.getStateId());
        }

        // 4. 退款给用户
        Customer customer = customerService.getById(order.getCustomerId());
        if (customer != null) {
            customer.setBalance(customer.getBalance() + order.getCancelPrice());
            customerService.updateById(customer);
        }

        return ResultVO.success("审核通过，退款成功");
    }

    @Override
    public ResultVO rejectOrder(Integer orderId) {
        // 1. 获取订单信息
        Orders order = getById(orderId);
        if (order == null) {
            return ResultVO.fail("订单不存在");
        }

        // 2. 根据退款金额决定回退状态
        if (order.getCancelPrice() == null || order.getCancelPrice() == 0) {
            // 退款金额为0 → 回退到未支付状态(1)
            order.setState(1);
        } else {
            // 退款金额不为0 → 回退到已支付状态(2)
            order.setState(2);
        }

        // 3. 更新订单状态
        updateById(order);

        return ResultVO.success("审核未通过，订单状态已更新");
    }

}
